using System.Reflection;
using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;

    public static T Inst
    {
        get
        {
            if (instance == null)
            {
                // 在场景中查找是否已存在该类型的实例
                instance = FindObjectOfType<T>();
                // 如果场景中不存在该类型的实例，则创建一个新的GameObject并添加该组件
                if (instance == null)
                {
                    GameObject singletonObject = new GameObject(typeof(T).Name + "_Singleton");
                    instance = singletonObject.AddComponent<T>();
                    DontDestroyOnLoad(singletonObject); // 保留在场景切换时不被销毁
                }
            }

            return instance;
        }
    }

    //使用virtual虚函数，子类继承可能还需要用Awake()
    private void Awake()
    {
        // 确保在场景切换时不会销毁该实例
        DontDestroyOnLoad(gameObject);
        // 检查是否存在重复的实例
        if (instance == null)
        {
            instance = this as T;
        }
        else
        {
            Debug.LogWarning("存在重复的单例" + typeof(T).Name + "删除");
            Destroy(gameObject);
        }

        Construct();
    }

    void OnDestroy()
    {
        Release();
        Destroy(gameObject);
    }

    protected virtual void Construct()
    {

    }

    protected virtual void Release()
    {

    }

    private void OnValidate()
    {
        var methods = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        //找方法
        var awake = false;
        var construct = false;
        var destroy = false;
        var release = false;

        foreach (var method in methods)
        {
            if (method.Name == nameof(Awake))
            {
                awake = true;
            }
            else if (method.Name == nameof(Construct))
            {
                construct = true;
            }
            else if (method.Name == nameof(Destroy))
            {
                destroy = true;
            }
            else if (method.Name == nameof(Release))
            {
                release = true;
            }
        }

        if ((awake && construct) || (destroy && release))
        {
            Debug.LogError("构造方法或析构方法重复,请检查" + instance.name);
        }
    }
}

public class SingletonNoMono<T> where T : class , new()
{
    private static T m_Instance;
    
    public static T Inst
    {
        get
        {
            if (m_Instance == null)
            {
                m_Instance = new T();
            }

            return m_Instance;
        }
    }
}